Add support for "Digital Mapping TrackLogs" (.trl) files.
authoroliskoli <oliskoli>
Tue, 29 Aug 2006 21:25:31 +0000 (21:25 +0000)
committeroliskoli <oliskoli>
Tue, 29 Aug 2006 21:25:31 +0000 (21:25 +0000)
Makefile.in
dmtlog.c [new file with mode: 0644]
reference/track/dmtlog-sample.gpx [new file with mode: 0644]
testo
vecs.c

index 59a4e8500286f0e60201ee9887143cf18701cef0..3838b60fe697f32870a3744397ef5a41d5ef2e0b 100644 (file)
@@ -53,7 +53,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o garmin_tables.o \
        tef_xml.o maggeo.o pathaway.o vitosmt.o gdb.o bcr.o coto.o \
        ignrando.o stmwpp.o msroute.o cst.o nmn4.o mag_pdb.o compegps.o \
        yahoo.o unicsv.o wfff_xml.o garmin_txt.o axim_gpb.o gpssim.o \
-       wbt-200.o stmsdf.o gtrnctr.o
+       wbt-200.o stmsdf.o gtrnctr.o dmtlog.o
 
 FILTERS=position.o duplicate.o arcdist.o polygon.o smplrout.o \
        reverse_route.o sort.o stackfilter.o trackfilter.o discard.o \
@@ -305,6 +305,8 @@ delgpl.o: delgpl.c defs.h config.h queue.h gbtypes.h cet.h cet_util.h \
   inifile.h
 discard.o: discard.c defs.h config.h queue.h gbtypes.h cet.h cet_util.h \
   inifile.h filterdefs.h
+dmtlog.o: dmtlog.c defs.h config.h queue.h gbtypes.h \
+  zlib/zlib.h jeeps/gpsmath.h xmlgeneric.h
 duplicate.o: duplicate.c defs.h config.h queue.h gbtypes.h cet.h \
   cet_util.h inifile.h filterdefs.h
 easygps.o: easygps.c defs.h config.h queue.h gbtypes.h cet.h cet_util.h \
diff --git a/dmtlog.c b/dmtlog.c
new file mode 100644 (file)
index 0000000..77a0ac0
--- /dev/null
+++ b/dmtlog.c
@@ -0,0 +1,719 @@
+/*
+
+    Support for Digital Mapping TrackLogs (.trl) files,
+
+    Copyright (C) 2006 Olaf Klein, o.b.klein@t-online.de
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+#include "defs.h"
+#include "jeeps/gpsmath.h"
+#include "xmlgeneric.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MYNAME "dmtlog"
+
+#define DEFLATE_BUFF_SIZE 16384
+
+static gbfile *fin, *fout;
+
+static char *xmlbin;
+static waypoint *xmlwpt;
+static route_head *xmltrk;
+static char *xmlgrid;
+static int xmldatum, datum_WGS84, datum_OSGB36;
+static double xmlEasting, xmlNorthing;
+static double xmlLatitude, xmlLongitude;
+static double xmlAltitude;
+
+#if !ZLIB_INHIBITED
+static int xmlbinsize;
+#endif
+
+static char header_written;
+static char *opt_index;
+static int track_index, this_index;
+
+static
+arglist_t dmtlog_args[] = {
+       { "index", &opt_index,
+               "Index of track (if more the one in source)", "1", ARGTYPE_INT, "1", NULL },
+       ARG_TERMINATOR
+};
+
+
+#if !ZLIB_INHIBITED
+static xg_callback tlog3a_xgcb_version, tlog3a_xgcb_length, tlog3a_xgcb_data;
+
+static xg_tag_mapping tlog3a_xgcb_map[] = {
+       { tlog3a_xgcb_version,  cb_cdata, "/CXMLSafe/Version" },
+       { tlog3a_xgcb_length,   cb_cdata, "/CXMLSafe/Length" },
+       { tlog3a_xgcb_data,     cb_cdata, "/CXMLSafe/Data" },
+       { NULL,         0,         NULL}
+};
+#endif
+
+static xg_callback tlog3b_xgcb_tfna, tlog3b_xgcb_tfdes;
+static xg_callback tlog3b_xgcb_wptst, tlog3b_xgcb_tptst;
+static xg_callback tlog3b_xgcb_tpten, tlog3b_xgcb_wpten;
+static xg_callback tlog3b_xgcb_wptid, tlog3b_xgcb_wptdt;
+static xg_callback tlog3b_xgcb_wptgr, tlog3b_xgcb_wptea;
+static xg_callback tlog3b_xgcb_wptno, tlog3b_xgcb_wptal;
+static xg_callback tlog3b_xgcb_tptdt;
+
+static xg_tag_mapping tlog3b_xgcb_map[] = {
+       { tlog3b_xgcb_tfna,     cb_cdata, "/CTrackFile/Name" },
+       { tlog3b_xgcb_tfdes,    cb_cdata, "/CTrackFile/Description" },
+       { tlog3b_xgcb_wptst,    cb_start, "/CTrackFile/CWayPoint" },
+       { tlog3b_xgcb_wptid,    cb_cdata, "/CTrackFile/CWayPoint/Id" },
+       { tlog3b_xgcb_wptdt,    cb_cdata, "/CTrackFile/CWayPoint/Datum" },
+       { tlog3b_xgcb_wptgr,    cb_cdata, "/CTrackFile/CWayPoint/Grid" },
+       { tlog3b_xgcb_wptea,    cb_cdata, "/CTrackFile/CWayPoint/Easting" },
+       { tlog3b_xgcb_wptno,    cb_cdata, "/CTrackFile/CWayPoint/Northing" },
+       { tlog3b_xgcb_wptal,    cb_cdata, "/CTrackFile/CWayPoint/Altitude" },
+       { tlog3b_xgcb_wpten,    cb_end,   "/CTrackFile/CWayPoint" },
+       { tlog3b_xgcb_tptst,    cb_start, "/CTrackFile/CTrackPoint" },
+       { tlog3b_xgcb_wptid,    cb_cdata, "/CTrackFile/CTrackPoint/Id" },
+       { tlog3b_xgcb_tptdt,    cb_cdata, "/CTrackFile/CTrackPoint/Datum" },
+       { tlog3b_xgcb_wptgr,    cb_cdata, "/CTrackFile/CTrackPoint/Grid" },
+       { tlog3b_xgcb_wptea,    cb_cdata, "/CTrackFile/CTrackPoint/Easting" },
+       { tlog3b_xgcb_wptno,    cb_cdata, "/CTrackFile/CTrackPoint/Northing" },
+       { tlog3b_xgcb_wptal,    cb_cdata, "/CTrackFile/CTrackPoint/Altitude" },
+       { tlog3b_xgcb_tpten,    cb_end,   "/CTrackFile/CTrackPoint" },
+       { NULL,         0,         NULL}
+};
+
+/* helpers */
+
+static void
+convert_datum(waypoint *wpt, int datum)
+{
+       if (datum != datum_WGS84) {
+               double lat = wpt->latitude;
+               double lon = wpt->longitude;
+               double alt = wpt->altitude;
+               GPS_Math_Known_Datum_To_WGS84_C(lat, lon, alt,
+                       &wpt->latitude, &wpt->longitude, &wpt->altitude, 
+                       datum);
+       }
+}
+
+
+static void
+finalize_pt(waypoint *wpt)
+{
+       if (strcmp(xmlgrid, "BNG") == 0) {
+               GPS_Math_NGENToAiry1830LatLon(xmlEasting, xmlNorthing, 
+               &wpt->latitude, &wpt->longitude);
+               xmldatum = datum_OSGB36;
+       }
+       else {
+               wpt->latitude = xmlLatitude;
+               wpt->longitude = xmlLongitude;
+       }
+       wpt->altitude = xmlAltitude;
+       convert_datum(wpt, xmldatum);
+}
+
+/* xml-reader callbacks */
+
+#if !ZLIB_INHIBITED
+static void    
+tlog3a_xgcb_version(const char *args, const char **unused)
+{
+       if (strcmp(args, "1") != 0)
+               fatal(MYNAME ": Unsupported file version '%s'!\n", args);
+}
+
+static void    
+tlog3a_xgcb_length(const char *args, const char **unused)
+{
+}
+
+static void    
+tlog3a_xgcb_data(const char *args, const char **unused)
+{
+       int len;
+       char *bin;
+       char *cin, *cout;
+       char cl, ch;
+       
+       len = strlen(args);
+       bin = xmalloc((len >> 1) + 1);
+       
+       cin = (char *)args;
+       cout = bin;
+       
+       cl = 0x10;
+       while (*cin) {
+               char c = *cin++;
+               
+               if (c == '\0') break;
+               else if ((c >= 'A') && (c <= 'F')) c -= 'A' - 10;
+               else if ((c >= 'a') && (c <= 'f')) c -= 'a' - 10;
+               else if ((c >= '0') && (c <= '9')) c -= '0';
+               else continue;
+
+               if (cl == 0x10) cl = c;
+               else {
+                       ch = (cl << 4) | c;
+                       *cout++ = ch;
+                       cl = 0x10;
+               }
+       }
+       xmlbin = bin;
+       xmlbinsize = (cout - bin);
+}
+#endif
+
+
+static void
+tlog3b_xgcb_tfna(const char *args, const char **unused)
+{
+       if (xmltrk == NULL) {
+               xmltrk = route_head_alloc();
+               track_add_head(xmltrk);
+       }
+       xmltrk->rte_name = strdup(args);
+}
+
+
+static void
+tlog3b_xgcb_tfdes(const char *args, const char **unused)
+{
+       if (xmltrk == NULL) {
+               xmltrk = route_head_alloc();
+               track_add_head(xmltrk);
+       }
+       xmltrk->rte_desc = strdup(args);
+}
+
+
+static void
+tlog3b_xgcb_wptst(const char *args, const char **unused)
+{
+       xmlwpt = waypt_new();
+       xmldatum = datum_WGS84;
+}
+
+
+static void
+tlog3b_xgcb_tptst(const char *args, const char **unused)
+{
+       xmlwpt = waypt_new();
+       xmldatum = datum_WGS84;
+}
+
+
+static void
+tlog3b_xgcb_tpten(const char *args, const char **unused)
+{
+       finalize_pt(xmlwpt);
+       
+       if (xmltrk == NULL) {
+               xmltrk = route_head_alloc();
+               track_add_head(xmltrk);
+       }
+       track_add_wpt(xmltrk, xmlwpt);
+       xmlwpt = NULL;
+}
+
+
+static void
+tlog3b_xgcb_wptid(const char *args, const char **unused)
+{
+       if (*args)
+               xmlwpt->shortname = xstrdup(args);
+}
+
+
+static void
+tlog3b_xgcb_wptdt(const char *args, const char **unused)
+{
+       xmldatum = GPS_Lookup_Datum_Index(args);
+}
+
+
+static void
+tlog3b_xgcb_wptgr(const char *args, const char **unused)
+{
+       if (xmlgrid != NULL) {
+               if (strcmp(xmlgrid, args) == 0) return;
+               xfree(xmlgrid);
+       }
+       xmlgrid = xstrdup(args);
+}
+
+
+static void
+tlog3b_xgcb_wptno(const char *args, const char **unused)
+{
+       xmlNorthing = atof(args);
+}
+
+
+static void
+tlog3b_xgcb_wptea(const char *args, const char **unused)
+{
+       xmlEasting = atof(args);
+}
+
+
+static void
+tlog3b_xgcb_wptal(const char *args, const char **unused)
+{
+       xmlAltitude = atof(args);
+}
+
+
+static void
+tlog3b_xgcb_tptdt(const char *args, const char **unused)
+{
+       xmldatum = GPS_Lookup_Datum_Index(args);
+}
+
+
+static void
+tlog3b_xgcb_wpten(const char *args, const char **unused)
+{
+       finalize_pt(xmlwpt);
+       waypt_add(xmlwpt);
+       xmlwpt = NULL;
+}
+
+
+static int
+read_datum(gbfile *f)
+{
+       int res;
+       char *d, *g;
+       
+       d = gbfgetpstr(f);
+       g = gbfgetpstr(f);
+       
+       res = GPS_Lookup_Datum_Index(d);
+       
+       if (*g && (strcmp(d, g) != 0)) {
+               fatal(MYNAME ": Unsupported combination of datum '%s' and grid '%s'!\n",
+                       d, g);
+       }
+       xfree(d);
+       xfree(g);
+       
+       return res;
+}
+
+
+static void
+read_CTrackFile(const int version)
+{
+       char buf[128];
+       gbuint32 ver;
+       gbint32 tcount, wcount;
+       gbint16 u1;
+       gbint32 ux;
+       route_head *track;
+       int i;
+       int datum;
+       
+       u1 = gbfgetint16(fin);
+
+       gbfread(buf, 1, 10, fin);
+       if ((u1 != 0x0a) || (strncmp("CTrackFile", buf, 10) != 0))
+               fatal(MYNAME ": Unknown or invalid track file.\n");
+
+       if (version == 8) {
+               for (i = 1; i <= 9; i++)
+                       gbfread(buf, 1, 4, fin);
+       }
+       ver = gbfgetint32(fin);
+       if (ver != version)
+               fatal(MYNAME ": Unknown or invalid track file (%d).\n", ver);
+       
+       ux = gbfgetint32(fin); // Unknown 2
+       ux = gbfgetint32(fin); // Unknown 3
+       ux = gbfgetint32(fin); // Unknown 4
+       
+       track = route_head_alloc();
+       track_add_head(track);
+       
+       /* S1 .. S9: comments, hints, jokes, aso */
+       for (i = 0; i < 9; i++) {
+               int c = gbfgetc(fin);
+               gbfseek(fin, c, SEEK_CUR);
+       }
+       
+       tcount = gbfgetint32(fin);
+       if (tcount > 0) {
+               datum = read_datum(fin);
+               if (version == 8) {
+                       int len;
+                       
+                       gbfread(buf, 1, 4, fin);
+                       len = gbfgetint16(fin);
+                       gbfseek(fin, len, SEEK_CUR);
+               }
+       }
+
+       while (tcount > 0)
+       {
+               waypoint *wpt;
+               
+               tcount--;
+               
+               if (version == 8)
+                       datum = read_datum(fin);
+
+               wpt = waypt_new();
+               
+               wpt->latitude = gbfgetdbl(fin);
+               wpt->longitude = gbfgetdbl(fin);
+               wpt->altitude = gbfgetdbl(fin);
+               
+               convert_datum(wpt, datum);
+               
+               track_add_wpt(track, wpt);
+               
+               if (version == 8)
+                       gbfseek(fin, 34, SEEK_CUR);
+       }
+
+       wcount = gbfgetint32(fin);
+       
+       if (wcount == 0) return;
+
+       if (version == 8) {
+               warning(MYNAME ": We don't yet support waypoints for this file version!\n");
+               return;
+       }
+               
+       datum = read_datum(fin);
+
+       while (wcount > 0) {
+               waypoint *wpt;
+               gbint32 namect, i;
+               
+               wcount--;
+
+               if (version == 8)
+                       datum = read_datum(fin);
+               
+               wpt = waypt_new();
+               
+               wpt->latitude = gbfgetdbl(fin);
+               wpt->longitude = gbfgetdbl(fin);
+               wpt->altitude = gbfgetdbl(fin);
+               
+               convert_datum(wpt, datum);
+               
+               namect = gbfgetint32(fin);
+               
+               // variants of shortname
+               
+               for (i = 0; i < namect; i++) {
+                       char *name = gbfgetpstr(fin);
+                       if (name && *name) {
+                               switch(i) {
+                                       case 0: wpt->description = xstrdup(name); break;
+                                       case 1: wpt->shortname = xstrdup(name); break;
+                               }
+                       }
+                       xfree(name);
+               }
+               if (version == 8)
+                       gbfseek(fin, 34, SEEK_CUR);
+               
+               waypt_add(wpt);
+       }
+}
+
+
+#if !ZLIB_INHIBITED
+
+static int
+inflate_buff(const char *buff, const size_t size, char **out_buff)
+{
+       int res = Z_OK;
+       z_stream strm;
+       char out[DEFLATE_BUFF_SIZE];
+       char *cout = NULL;
+       gbuint32 bytes = 0;
+       gbuint32 have;
+
+       strm.zalloc = Z_NULL;
+       strm.zfree = Z_NULL;
+       strm.opaque = Z_NULL;
+       strm.avail_in = 0;
+       strm.next_in = Z_NULL;
+       
+       res = inflateInit(&strm);
+       if (res != Z_OK) {
+               return res;
+       }
+       
+       strm.avail_in = size;
+       strm.next_in = (void *)buff;
+       
+       do {
+               strm.avail_out = DEFLATE_BUFF_SIZE;
+               strm.next_out = (void *)out;
+               res = inflate(&strm, Z_NO_FLUSH);
+               
+               switch (res) {
+                       case Z_NEED_DICT:
+                               res = Z_DATA_ERROR;     /* and fall through */
+                       case Z_DATA_ERROR:
+                       case Z_MEM_ERROR:
+                               (void)inflateEnd(&strm);
+                               return res;
+               }
+               have = DEFLATE_BUFF_SIZE - strm.avail_out;
+               if (have > 0) {
+                       cout = xrealloc(cout, bytes + have);
+                       memcpy(cout+bytes, out, have);
+                       bytes+=have;
+               }
+       } while (strm.avail_out == 0);
+       
+       *out_buff = cout;
+       return res;
+}
+
+
+static void
+read_CXMLSafe(void)
+{
+       char *xmlstr = NULL;
+       
+       xmlbin = NULL;
+       xmlbinsize = 0;
+       
+       xml_init(fin->name, tlog3a_xgcb_map, NULL);
+       xml_read();
+       xml_deinit();
+       
+       if (xmlbin != NULL) {
+               inflate_buff(xmlbin, xmlbinsize, &xmlstr);
+               xfree(xmlbin);
+
+               xml_init(NULL, tlog3b_xgcb_map, NULL);
+               xml_readstring(xmlstr);
+               xml_deinit();
+               
+               xfree(xmlstr);
+       }
+}
+
+#endif
+
+static void
+read_XML(void)
+{
+       xml_init(fin->name, tlog3b_xgcb_map, NULL);
+       xml_read();
+       xml_deinit();
+       
+       return;
+}
+
+/*******************************************************************************
+* %%%        global callbacks called by gpsbabel main process              %%% *
+*******************************************************************************/
+
+static void
+dmtlog_rd_init(const char *fname)
+{
+       fin = gbfopen_le(fname, "rb", MYNAME);
+       
+       datum_OSGB36 = GPS_Lookup_Datum_Index("OSGB36");
+       datum_WGS84 = GPS_Lookup_Datum_Index("WGS84");
+       
+       xmlbin = NULL;
+       xmltrk = NULL;
+       xmlwpt = NULL;
+       xmlgrid = NULL;
+}
+
+static void 
+dmtlog_rd_deinit(void)
+{
+       gbfclose(fin);
+       if (xmlgrid != NULL) xfree(xmlgrid);
+}
+
+static void
+dmtlog_read(void)
+{
+       switch(gbfgetuint32(fin)) {
+       
+               case 0x4FFFF:
+                       read_CTrackFile(4);
+                       break;
+
+               case 0x8FFFF:
+                       read_CTrackFile(8);
+                       break;
+                       
+               case 0x4d58433c:
+#if !ZLIB_INHIBITED
+                       read_CXMLSafe();
+#else
+                       fatal(MYNAME ": Zlib was not included in this build.\n");
+#endif                 
+                       break;
+               case 0x7254433c:
+                       read_XML();
+                       break;
+
+               default:
+                       fatal(MYNAME ": Unknown or unsupported file type.\n");
+       }
+}
+
+static void
+dmtlog_wr_init(const char *fname)
+{
+       fout = gbfopen_le(fname, "wb", MYNAME);
+}
+
+static void
+dmtlog_wr_deinit(void)
+{
+       gbfclose(fout);
+}
+
+static void
+write_header(const route_head *trk)
+{
+       int count, i;
+       char *cout;
+       const char ZERO = '\0';
+       
+       header_written = 1;
+       
+       count = 0;
+       if (trk != NULL) {
+               queue *curr, *prev;
+               QUEUE_FOR_EACH(&trk->waypoint_list, curr, prev) count++;
+       }
+       gbfputpstr(trk && trk->rte_name && *trk->rte_name ? trk->rte_name : "Name", fout);
+       
+       xasprintf(&cout, "%d trackpoints and %d waypoints", count, waypt_count());
+       gbfputpstr(cout, fout);
+       xfree(cout);
+       
+       for (i = 3; i <= 8; i++) gbfputc(ZERO, fout);
+       gbfputpstr("GPSBabel", fout);
+       gbfputint32(count, fout);
+       if (count > 0) {
+               gbfputpstr("WGS84", fout);
+               gbfputpstr("WGS84", fout);
+       }
+}
+
+static void
+track_hdr_cb(const route_head *trk)
+{
+       
+       this_index++;
+       if (this_index != track_index) return;
+       write_header(trk);
+}
+
+static void
+track_tlr_cb(const route_head *trk)
+{
+}
+
+static void
+track_wpt_cb(const waypoint *wpt)
+{
+       if (this_index != track_index) return;
+       
+       gbfputdbl(wpt->latitude, fout);
+       gbfputdbl(wpt->longitude, fout);
+       gbfputdbl(wpt->altitude, fout);
+}
+
+static void
+wpt_cb(const waypoint *wpt)
+{
+       int names;
+       
+       gbfputdbl(wpt->latitude, fout);
+       gbfputdbl(wpt->longitude, fout);
+       gbfputdbl(wpt->altitude, fout);
+       
+       names = 1;
+       if (wpt->description && *wpt->description) names = 2;
+       gbfputint32(names, fout);
+       if (names > 1) gbfputpstr(wpt->description, fout);
+       gbfputpstr(wpt->shortname && *wpt->shortname ? wpt->shortname : "Name", fout);
+}
+
+static void
+dmtlog_write(void)
+{
+       track_index = atoi(opt_index);
+       /* ... validate index */
+       
+       gbfputint32(0x4FFFF, fout);
+       gbfputuint16(0x0A, fout);
+       gbfputs("CTrackFile", fout);
+       gbfputint32(4, fout);
+       gbfputint32(1, fout);
+       gbfputint32(0x100001, fout);
+       gbfputuint32((const gbuint32)gpsbabel_now, fout);
+       
+       header_written = 0;
+       this_index = 0;
+       track_disp_all(track_hdr_cb, track_tlr_cb, track_wpt_cb);
+       if (!header_written) 
+               write_header(NULL);
+       gbfputint32(waypt_count(), fout);
+       if (waypt_count() > 0) {
+               gbfputpstr("WGS84", fout);
+               gbfputpstr("WGS84", fout);
+               waypt_disp_all(wpt_cb);
+       }
+}
+
+/**************************************************************************/
+
+ff_vecs_t dmtlog_vecs = {
+       ff_type_file,
+       { 
+               ff_cap_read | ff_cap_write      /* waypoints */, 
+               ff_cap_read | ff_cap_write      /* tracks */, 
+               ff_cap_none                     /* routes */
+       },
+       dmtlog_rd_init, 
+       dmtlog_wr_init,
+       dmtlog_rd_deinit,       
+       dmtlog_wr_deinit,
+       dmtlog_read,
+       dmtlog_write,
+       NULL,
+       dmtlog_args,
+       CET_CHARSET_ASCII, 0
+
+};
+
+/**************************************************************************/
diff --git a/reference/track/dmtlog-sample.gpx b/reference/track/dmtlog-sample.gpx
new file mode 100644 (file)
index 0000000..fc52a5c
--- /dev/null
@@ -0,0 +1,669 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx
+ version="1.0"
+creator="GPSBabel - http://www.gpsbabel.org"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xmlns="http://www.topografix.com/GPX/1/0"
+xsi:schemaLocation="http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd">
+<time>1970-01-01T00:00:00Z</time>
+<bounds minlat="30.045517000" minlon ="-91.610567000" maxlat="42.468655000" maxlon="-71.102973000" />
+<wpt lat="42.438878000" lon="-71.119277000">
+  <ele>44.586548</ele>
+  <name>5066</name>
+  <cmt>5066</cmt>
+  <desc>5066</desc>
+</wpt>
+<wpt lat="42.439227000" lon="-71.119689000">
+  <ele>57.607200</ele>
+  <name>5067</name>
+  <cmt>5067</cmt>
+  <desc>5067</desc>
+</wpt>
+<wpt lat="42.438917000" lon="-71.116146000">
+  <ele>44.826904</ele>
+  <name>5096</name>
+  <cmt>5096</cmt>
+  <desc>5096</desc>
+</wpt>
+<wpt lat="42.443904000" lon="-71.122044000">
+  <ele>50.594727</ele>
+  <name>5142</name>
+  <cmt>5142</cmt>
+  <desc>5142</desc>
+</wpt>
+<wpt lat="42.447298000" lon="-71.121447000">
+  <ele>127.711200</ele>
+  <name>5156</name>
+  <cmt>5156</cmt>
+  <desc>5156</desc>
+</wpt>
+<wpt lat="42.454873000" lon="-71.125094000">
+  <ele>96.926400</ele>
+  <name>5224</name>
+  <cmt>5224</cmt>
+  <desc>5224</desc>
+</wpt>
+<wpt lat="42.459079000" lon="-71.124988000">
+  <ele>82.600800</ele>
+  <name>5229</name>
+  <cmt>5229</cmt>
+  <desc>5229</desc>
+</wpt>
+<wpt lat="42.456979000" lon="-71.124474000">
+  <ele>82.905600</ele>
+  <name>5237</name>
+  <cmt>5237</cmt>
+  <desc>5237</desc>
+</wpt>
+<wpt lat="42.454401000" lon="-71.120990000">
+  <ele>66.696655</ele>
+  <name>5254</name>
+  <cmt>5254</cmt>
+  <desc>5254</desc>
+</wpt>
+<wpt lat="42.451442000" lon="-71.121746000">
+  <ele>74.627442</ele>
+  <name>5258</name>
+  <cmt>5258</cmt>
+  <desc>5258</desc>
+</wpt>
+<wpt lat="42.454404000" lon="-71.120660000">
+  <ele>65.254761</ele>
+  <name>5264</name>
+  <cmt>5264</cmt>
+  <desc>5264</desc>
+</wpt>
+<wpt lat="42.457761000" lon="-71.121045000">
+  <ele>77.419200</ele>
+  <name>526708</name>
+  <cmt>526708</cmt>
+  <desc>526708</desc>
+</wpt>
+<wpt lat="42.457089000" lon="-71.120313000">
+  <ele>74.676000</ele>
+  <name>526750</name>
+  <cmt>526750</cmt>
+  <desc>526750</desc>
+</wpt>
+<wpt lat="42.456592000" lon="-71.119676000">
+  <ele>78.713135</ele>
+  <name>527614</name>
+  <cmt>527614</cmt>
+  <desc>527614</desc>
+</wpt>
+<wpt lat="42.456252000" lon="-71.119356000">
+  <ele>78.713135</ele>
+  <name>527631</name>
+  <cmt>527631</cmt>
+  <desc>527631</desc>
+</wpt>
+<wpt lat="42.458148000" lon="-71.119135000">
+  <ele>68.275200</ele>
+  <name>5278</name>
+  <cmt>5278</cmt>
+  <desc>5278</desc>
+</wpt>
+<wpt lat="42.459377000" lon="-71.117693000">
+  <ele>64.008000</ele>
+  <name>5289</name>
+  <cmt>5289</cmt>
+  <desc>5289</desc>
+</wpt>
+<wpt lat="42.464183000" lon="-71.119828000">
+  <ele>52.997925</ele>
+  <name>5374FIRE</name>
+  <cmt>5374FIRE</cmt>
+  <desc>5374FIRE</desc>
+</wpt>
+<wpt lat="42.465650000" lon="-71.119399000">
+  <ele>56.388000</ele>
+  <name>5376</name>
+  <cmt>5376</cmt>
+  <desc>5376</desc>
+</wpt>
+<wpt lat="42.439018000" lon="-71.114456000">
+  <ele>56.388000</ele>
+  <name>6006</name>
+  <cmt>600698</cmt>
+  <desc>600698</desc>
+</wpt>
+<wpt lat="42.438594000" lon="-71.114803000">
+  <ele>46.028564</ele>
+  <name>6006BLUE</name>
+  <cmt>6006BLUE</cmt>
+  <desc>6006BLUE</desc>
+</wpt>
+<wpt lat="42.436757000" lon="-71.113223000">
+  <ele>37.616943</ele>
+  <name>6014MEADOW</name>
+  <cmt>6014MEADOW</cmt>
+  <desc>6014MEADOW</desc>
+</wpt>
+<wpt lat="42.441754000" lon="-71.113220000">
+  <ele>56.388000</ele>
+  <name>6029</name>
+  <cmt>6029</cmt>
+  <desc>6029</desc>
+</wpt>
+<wpt lat="42.436243000" lon="-71.109075000">
+  <ele>50.292000</ele>
+  <name>6053</name>
+  <cmt>6053</cmt>
+  <desc>6053</desc>
+</wpt>
+<wpt lat="42.439250000" lon="-71.107500000">
+  <ele>25.603200</ele>
+  <name>6066</name>
+  <cmt>6066</cmt>
+  <desc>6066</desc>
+</wpt>
+<wpt lat="42.439764000" lon="-71.107582000">
+  <ele>34.442400</ele>
+  <name>6067</name>
+  <cmt>6067</cmt>
+  <desc>6067</desc>
+</wpt>
+<wpt lat="42.434766000" lon="-71.105874000">
+  <ele>30.480000</ele>
+  <name>6071</name>
+  <cmt>6071</cmt>
+  <desc>6071</desc>
+</wpt>
+<wpt lat="42.433304000" lon="-71.106599000">
+  <ele>15.240000</ele>
+  <name>6073</name>
+  <cmt>6073</cmt>
+  <desc>6073</desc>
+</wpt>
+<wpt lat="42.437338000" lon="-71.104772000">
+  <ele>37.795200</ele>
+  <name>6084</name>
+  <cmt>6084</cmt>
+  <desc>6084</desc>
+</wpt>
+<wpt lat="42.442196000" lon="-71.110975000">
+  <ele>64.008000</ele>
+  <name>6130</name>
+  <cmt>6130</cmt>
+  <desc>6130</desc>
+</wpt>
+<wpt lat="42.442981000" lon="-71.111441000">
+  <ele>64.008000</ele>
+  <name>6131</name>
+  <cmt>6131</cmt>
+  <desc>6131</desc>
+</wpt>
+<wpt lat="42.444773000" lon="-71.108882000">
+  <ele>62.788800</ele>
+  <name>6153</name>
+  <cmt>6153</cmt>
+  <desc>6153</desc>
+</wpt>
+<wpt lat="42.443592000" lon="-71.106301000">
+  <ele>55.473600</ele>
+  <name>6171</name>
+  <cmt>6171</cmt>
+  <desc>6171</desc>
+</wpt>
+<wpt lat="42.447804000" lon="-71.106624000">
+  <ele>62.484000</ele>
+  <name>6176</name>
+  <cmt>6176</cmt>
+  <desc>6176</desc>
+</wpt>
+<wpt lat="42.448448000" lon="-71.106158000">
+  <ele>62.179200</ele>
+  <name>6177</name>
+  <cmt>6177</cmt>
+  <desc>6177</desc>
+</wpt>
+<wpt lat="42.453415000" lon="-71.106783000">
+  <ele>69.799200</ele>
+  <name>6272</name>
+  <cmt>6272</cmt>
+  <desc>6272</desc>
+</wpt>
+<wpt lat="42.453434000" lon="-71.107253000">
+  <ele>73.152000</ele>
+  <name>6272</name>
+  <cmt>6272</cmt>
+  <desc>6272</desc>
+</wpt>
+<wpt lat="42.458298000" lon="-71.106771000">
+  <ele>70.104000</ele>
+  <name>6278</name>
+  <cmt>6278</cmt>
+  <desc>6278</desc>
+</wpt>
+<wpt lat="42.451430000" lon="-71.105413000">
+  <ele>57.564209</ele>
+  <name>6280</name>
+  <cmt>6280</cmt>
+  <desc>6280</desc>
+</wpt>
+<wpt lat="42.453845000" lon="-71.105206000">
+  <ele>66.696655</ele>
+  <name>6283</name>
+  <cmt>6283</cmt>
+  <desc>6283</desc>
+</wpt>
+<wpt lat="42.459986000" lon="-71.106170000">
+  <ele>72.945191</ele>
+  <name>6289</name>
+  <cmt>6289</cmt>
+  <desc>6289</desc>
+</wpt>
+<wpt lat="42.457616000" lon="-71.105116000">
+  <ele>72.847200</ele>
+  <name>6297</name>
+  <cmt>6297</cmt>
+  <desc>6297</desc>
+</wpt>
+<wpt lat="42.467110000" lon="-71.113574000">
+  <ele>53.644800</ele>
+  <name>6328</name>
+  <cmt>6328</cmt>
+  <desc>6328</desc>
+</wpt>
+<wpt lat="42.464202000" lon="-71.109863000">
+  <ele>43.891200</ele>
+  <name>6354</name>
+  <cmt>6354</cmt>
+  <desc>6354</desc>
+</wpt>
+<wpt lat="42.466459000" lon="-71.110067000">
+  <ele>48.768000</ele>
+  <name>635722</name>
+  <cmt>635722</cmt>
+  <desc>635722</desc>
+</wpt>
+<wpt lat="42.466557000" lon="-71.109410000">
+  <ele>49.072800</ele>
+  <name>635783</name>
+  <cmt>635783</cmt>
+  <desc>635783</desc>
+</wpt>
+<wpt lat="42.463495000" lon="-71.107117000">
+  <ele>62.484000</ele>
+  <name>6373</name>
+  <cmt>6373</cmt>
+  <desc>6373</desc>
+</wpt>
+<wpt lat="42.401051000" lon="-71.110241000">
+  <ele>3.962400</ele>
+  <name>6634</name>
+  <cmt>6634</cmt>
+  <desc>6634</desc>
+</wpt>
+<wpt lat="42.432621000" lon="-71.106532000">
+  <ele>13.411200</ele>
+  <name>6979</name>
+  <cmt>6979</cmt>
+  <desc>6979</desc>
+</wpt>
+<wpt lat="42.431033000" lon="-71.107883000">
+  <ele>34.012085</ele>
+  <name>6997</name>
+  <cmt>6997</cmt>
+  <desc>6997</desc>
+</wpt>
+<wpt lat="42.465687000" lon="-71.107360000">
+  <ele>87.782400</ele>
+  <name>BEAR HILL</name>
+  <cmt>BEAR HILL TOWER</cmt>
+  <desc>BEAR HILL TOWER</desc>
+</wpt>
+<wpt lat="42.430950000" lon="-71.107628000">
+  <ele>23.469600</ele>
+  <name>BELLEVUE</name>
+  <cmt>BELLEVUE</cmt>
+  <desc>BELLEVUE</desc>
+</wpt>
+<wpt lat="42.438666000" lon="-71.114079000">
+  <ele>43.384766</ele>
+  <name>6016</name>
+  <cmt>Bike Loop Connector</cmt>
+  <desc>Bike Loop Connector</desc>
+</wpt>
+<wpt lat="42.456469000" lon="-71.124651000">
+  <ele>89.916000</ele>
+  <name>5236BRIDGE</name>
+  <cmt>Bridge</cmt>
+  <desc>Bridge</desc>
+</wpt>
+<wpt lat="42.465759000" lon="-71.119815000">
+  <ele>55.473600</ele>
+  <name>5376BRIDGE</name>
+  <cmt>Bridge</cmt>
+  <desc>Bridge</desc>
+</wpt>
+<wpt lat="42.442993000" lon="-71.105878000">
+  <ele>52.730400</ele>
+  <name>6181CROSS</name>
+  <cmt>Crossing</cmt>
+  <desc>Crossing</desc>
+</wpt>
+<wpt lat="42.435472000" lon="-71.109664000">
+  <ele>45.110400</ele>
+  <name>6042CROSS</name>
+  <cmt>Crossing</cmt>
+  <desc>Crossing</desc>
+</wpt>
+<wpt lat="42.458516000" lon="-71.103646000">
+  <name>DARKHOLLPO</name>
+  <cmt>Dark Hollow Pond</cmt>
+  <desc>Dark Hollow Pond</desc>
+</wpt>
+<wpt lat="42.443109000" lon="-71.112675000">
+  <ele>56.083200</ele>
+  <name>6121DEAD</name>
+  <cmt>Dead End</cmt>
+  <desc>Dead End</desc>
+</wpt>
+<wpt lat="42.449866000" lon="-71.119298000">
+  <ele>117.043200</ele>
+  <name>5179DEAD</name>
+  <cmt>Dead End</cmt>
+  <desc>Dead End</desc>
+</wpt>
+<wpt lat="42.459629000" lon="-71.116524000">
+  <ele>69.494400</ele>
+  <name>5299DEAD</name>
+  <cmt>Dead End</cmt>
+  <desc>Dead End</desc>
+</wpt>
+<wpt lat="42.465485000" lon="-71.119148000">
+  <ele>56.997600</ele>
+  <name>5376DEAD</name>
+  <cmt>Dead End</cmt>
+  <desc>Dead End</desc>
+</wpt>
+<wpt lat="42.462776000" lon="-71.109986000">
+  <ele>46.939200</ele>
+  <name>6353DEAD</name>
+  <cmt>Dead End</cmt>
+  <desc>Dead End</desc>
+</wpt>
+<wpt lat="42.446793000" lon="-71.108784000">
+  <ele>61.264800</ele>
+  <name>6155DEAD</name>
+  <cmt>Dead End</cmt>
+  <desc>Dead End</desc>
+</wpt>
+<wpt lat="42.451204000" lon="-71.126602000">
+  <ele>110.947200</ele>
+  <name>GATE14</name>
+  <cmt>Gate 14</cmt>
+  <desc>Gate 14</desc>
+</wpt>
+<wpt lat="42.458499000" lon="-71.122078000">
+  <ele>77.724000</ele>
+  <name>GATE16</name>
+  <cmt>Gate 16</cmt>
+  <desc>Gate 16</desc>
+</wpt>
+<wpt lat="42.459376000" lon="-71.119238000">
+  <ele>65.836800</ele>
+  <name>GATE17</name>
+  <cmt>Gate 17</cmt>
+  <desc>Gate 17</desc>
+</wpt>
+<wpt lat="42.466353000" lon="-71.119240000">
+  <ele>57.302400</ele>
+  <name>GATE19</name>
+  <cmt>Gate 19</cmt>
+  <desc>Gate 19</desc>
+</wpt>
+<wpt lat="42.468655000" lon="-71.107697000">
+  <ele>49.377600</ele>
+  <name>GATE21</name>
+  <cmt>Gate 21</cmt>
+  <desc>Gate 21</desc>
+</wpt>
+<wpt lat="42.456718000" lon="-71.102973000">
+  <ele>81.076800</ele>
+  <name>GATE24</name>
+  <cmt>Gate 24</cmt>
+  <desc>Gate 24</desc>
+</wpt>
+<wpt lat="42.430847000" lon="-71.107690000">
+  <ele>21.515015</ele>
+  <name>GATE5</name>
+  <cmt>Gate 5</cmt>
+  <desc>Gate 5</desc>
+</wpt>
+<wpt lat="42.431240000" lon="-71.109236000">
+  <ele>26.561890</ele>
+  <name>GATE6</name>
+  <cmt>Gate 6</cmt>
+  <desc>Gate 6</desc>
+</wpt>
+<wpt lat="42.439502000" lon="-71.106556000">
+  <ele>32.004000</ele>
+  <name>6077LOGS</name>
+  <cmt>Log Crossing</cmt>
+  <desc>Log Crossing</desc>
+</wpt>
+<wpt lat="42.449765000" lon="-71.122320000">
+  <ele>119.809082</ele>
+  <name>5148NANEPA</name>
+  <cmt>Nanepashemet Road Crossing</cmt>
+  <desc>Nanepashemet Road Crossing</desc>
+</wpt>
+<wpt lat="42.457388000" lon="-71.119845000">
+  <ele>73.761600</ele>
+  <name>5267OBSTAC</name>
+  <cmt>Obstacle</cmt>
+  <desc>Obstacle</desc>
+</wpt>
+<wpt lat="42.434980000" lon="-71.109942000">
+  <ele>45.307495</ele>
+  <name>PANTHRCAVE</name>
+  <cmt>Panther Cave</cmt>
+  <desc>Panther Cave</desc>
+</wpt>
+<wpt lat="42.453256000" lon="-71.121211000">
+  <ele>77.992066</ele>
+  <name>5252PURPLE</name>
+  <cmt>Purple Rock Hill</cmt>
+  <desc>Purple Rock Hill</desc>
+</wpt>
+<wpt lat="42.457734000" lon="-71.117481000">
+  <ele>67.970400</ele>
+  <name>5287WATER</name>
+  <cmt>Reservoir</cmt>
+  <desc>Reservoir</desc>
+</wpt>
+<wpt lat="42.459278000" lon="-71.124574000">
+  <ele>81.076800</ele>
+  <name>5239ROAD</name>
+  <cmt>Road</cmt>
+  <desc>Road</desc>
+</wpt>
+<wpt lat="42.458782000" lon="-71.118991000">
+  <ele>67.360800</ele>
+  <name>5278ROAD</name>
+  <cmt>Road</cmt>
+  <desc>Road</desc>
+</wpt>
+<wpt lat="42.439993000" lon="-71.120925000">
+  <ele>53.949600</ele>
+  <name>5058ROAD</name>
+  <cmt>ROAD CROSSING</cmt>
+  <desc>ROAD CROSSING</desc>
+</wpt>
+<wpt lat="42.453415000" lon="-71.106782000">
+  <ele>69.799200</ele>
+  <name>SHEEPFOLD</name>
+  <cmt>Sheepfold Parking Lot</cmt>
+  <desc>Sheepfold Parking Lot</desc>
+</wpt>
+<wpt lat="42.455956000" lon="-71.107483000">
+  <ele>64.008000</ele>
+  <name>SOAPBOX</name>
+  <cmt>Soap Box Derby Track</cmt>
+  <desc>Soap Box Derby Track</desc>
+</wpt>
+<wpt lat="42.465913000" lon="-71.119328000">
+  <ele>64.533692</ele>
+  <name>5376STREAM</name>
+  <cmt>Stream Crossing</cmt>
+  <desc>Stream Crossing</desc>
+</wpt>
+<wpt lat="42.445359000" lon="-71.122845000">
+  <ele>61.649902</ele>
+  <name>5144SUMMIT</name>
+  <cmt>Summit</cmt>
+  <desc>Summit</desc>
+</wpt>
+<wpt lat="42.441727000" lon="-71.121676000">
+  <ele>67.360800</ele>
+  <name>5150TANK</name>
+  <cmt>WATER TANK</cmt>
+  <desc>WATER TANK</desc>
+</wpt>
+<trk>
+<trkseg>
+<trkpt lat="30.062183000" lon="-91.610350000">
+  <ele>1.000000</ele>
+</trkpt>
+<trkpt lat="30.062783000" lon="-91.610567000">
+</trkpt>
+<trkpt lat="30.062700000" lon="-91.608267000">
+</trkpt>
+<trkpt lat="30.062333000" lon="-91.607383000">
+</trkpt>
+<trkpt lat="30.061533000" lon="-91.605283000">
+</trkpt>
+<trkpt lat="30.059783000" lon="-91.599400000">
+</trkpt>
+<trkpt lat="30.057800000" lon="-91.596683000">
+</trkpt>
+<trkpt lat="30.055383000" lon="-91.594900000">
+</trkpt>
+<trkpt lat="30.053883000" lon="-91.592617000">
+</trkpt>
+<trkpt lat="30.049733000" lon="-91.589750000">
+</trkpt>
+<trkpt lat="30.049017000" lon="-91.589883000">
+</trkpt>
+<trkpt lat="30.048800000" lon="-91.592933000">
+</trkpt>
+<trkpt lat="30.046233000" lon="-91.596450000">
+</trkpt>
+<trkpt lat="30.045517000" lon="-91.598717000">
+</trkpt>
+<trkpt lat="30.047300000" lon="-91.600267000">
+</trkpt>
+<trkpt lat="30.047000000" lon="-91.599633000">
+  <ele>2.000000</ele>
+</trkpt>
+<trkpt lat="30.046433000" lon="-91.599467000">
+</trkpt>
+<trkpt lat="30.046200000" lon="-91.598950000">
+  <ele>1.000000</ele>
+</trkpt>
+<trkpt lat="30.046367000" lon="-91.597733000">
+</trkpt>
+<trkpt lat="30.046350000" lon="-91.597167000">
+</trkpt>
+<trkpt lat="30.046783000" lon="-91.596333000">
+</trkpt>
+<trkpt lat="30.047450000" lon="-91.595200000">
+</trkpt>
+<trkpt lat="30.047800000" lon="-91.594767000">
+  <ele>2.000000</ele>
+</trkpt>
+<trkpt lat="30.048250000" lon="-91.594083000">
+  <ele>1.000000</ele>
+</trkpt>
+<trkpt lat="30.048683000" lon="-91.593800000">
+  <ele>1.000000</ele>
+</trkpt>
+<trkpt lat="30.049350000" lon="-91.593850000">
+</trkpt>
+<trkpt lat="30.050317000" lon="-91.593983000">
+  <ele>2.000000</ele>
+</trkpt>
+<trkpt lat="30.050783000" lon="-91.594117000">
+</trkpt>
+<trkpt lat="30.051233000" lon="-91.594367000">
+</trkpt>
+<trkpt lat="30.051800000" lon="-91.594367000">
+</trkpt>
+<trkpt lat="30.052217000" lon="-91.594667000">
+</trkpt>
+<trkpt lat="30.053017000" lon="-91.594683000">
+</trkpt>
+<trkpt lat="30.054867000" lon="-91.595200000">
+  <ele>6.000000</ele>
+</trkpt>
+<trkpt lat="30.053733000" lon="-91.594933000">
+  <ele>2.000000</ele>
+</trkpt>
+<trkpt lat="30.053183000" lon="-91.594783000">
+</trkpt>
+<trkpt lat="30.052633000" lon="-91.594833000">
+</trkpt>
+<trkpt lat="30.052450000" lon="-91.595433000">
+</trkpt>
+<trkpt lat="30.052483000" lon="-91.595967000">
+</trkpt>
+<trkpt lat="30.052650000" lon="-91.596783000">
+  <ele>1.000000</ele>
+</trkpt>
+<trkpt lat="30.053133000" lon="-91.597850000">
+</trkpt>
+<trkpt lat="30.053617000" lon="-91.597967000">
+</trkpt>
+<trkpt lat="30.053967000" lon="-91.597767000">
+  <ele>6.000000</ele>
+</trkpt>
+<trkpt lat="30.053617000" lon="-91.598083000">
+</trkpt>
+<trkpt lat="30.053200000" lon="-91.597917000">
+</trkpt>
+<trkpt lat="30.052817000" lon="-91.597517000">
+</trkpt>
+<trkpt lat="30.052567000" lon="-91.596933000">
+</trkpt>
+<trkpt lat="30.052333000" lon="-91.596433000">
+</trkpt>
+<trkpt lat="30.052250000" lon="-91.595683000">
+</trkpt>
+<trkpt lat="30.052217000" lon="-91.595017000">
+</trkpt>
+<trkpt lat="30.051883000" lon="-91.594700000">
+</trkpt>
+<trkpt lat="30.051050000" lon="-91.594400000">
+</trkpt>
+<trkpt lat="30.050567000" lon="-91.594233000">
+</trkpt>
+<trkpt lat="30.050183000" lon="-91.594100000">
+</trkpt>
+<trkpt lat="30.049100000" lon="-91.593717000">
+</trkpt>
+<trkpt lat="30.048450000" lon="-91.594250000">
+</trkpt>
+<trkpt lat="30.048083000" lon="-91.594750000">
+</trkpt>
+<trkpt lat="30.047500000" lon="-91.595450000">
+  <ele>7.000000</ele>
+</trkpt>
+<trkpt lat="30.047067000" lon="-91.596000000">
+</trkpt>
+<trkpt lat="30.046633000" lon="-91.596600000">
+</trkpt>
+<trkpt lat="30.046400000" lon="-91.597650000">
+</trkpt>
+<trkpt lat="30.046233000" lon="-91.598467000">
+</trkpt>
+<trkpt lat="30.046317000" lon="-91.598967000">
+</trkpt>
+<trkpt lat="30.046783000" lon="-91.599283000">
+</trkpt>
+<trkpt lat="30.047133000" lon="-91.599667000">
+</trkpt>
+</trkseg>
+</trk>
+</gpx>
diff --git a/testo b/testo
index 9000ea3a4d85af5ba0653714b9b0d6bf8a0b8e7b..cc28d0f24bf7fd2636e01e74f1f337169eede338 100755 (executable)
--- a/testo
+++ b/testo
@@ -1100,6 +1100,14 @@ compare ${TMPDIR}/stmsdf-route.sdf ${REFERENCE}/route/stmsdf-route.sdf
 ${PNAME} -i stmsdf -f ${TMPDIR}/stmsdf-track.sdf -f ${TMPDIR}/stmsdf-route.sdf -o garmin_txt,prec=2 -F ${TMPDIR}/stmsdf.txt
 compare ${TMPDIR}/stmsdf.txt ${REFERENCE}/stmsdf.txt
 
+#
+# Digital Mapping Tracklogs
+#
+rm -f ${TMPDIR}/dmtlog*
+${PNAME} -i gpx -f ${REFERENCE}/expertgps.gpx -o dmtlog -F ${TMPDIR}/dmtlog-sample.trl
+${PNAME} -i dmtlog -f ${TMPDIR}/dmtlog-sample.trl -o gpx -F ${TMPDIR}/dmtlog-sample.gpx
+compare ${TMPDIR}/dmtlog-sample.gpx ${REFERENCE}/track/dmtlog-sample.gpx
+
 #
 # gzipped file i/o
 #
diff --git a/vecs.c b/vecs.c
index e39af20c567d69b319cc54283a96c278dc1281aa..32aa0f6bda9798cd5cf703bb5c5a42278e3ace94 100644 (file)
--- a/vecs.c
+++ b/vecs.c
@@ -110,6 +110,7 @@ extern ff_vecs_t yahoo_vecs;
 extern ff_vecs_t wbt_svecs;
 extern ff_vecs_t wbt_fvecs;
 extern ff_vecs_t gtc_vecs;
+extern ff_vecs_t dmtlog_vecs;
 
 static
 vecs_t vec_list[] = {
@@ -600,6 +601,12 @@ vecs_t vec_list[] = {
                "Garmin Training Center"
                "xml"
        },
+       {
+               &dmtlog_vecs,
+               "dmtlog",
+               "Digital Mapping TrackLogs (.trl)",
+               "trl"
+       },
        {
                NULL,
                NULL,